package com.aivin.h16_lib;

import android.os.SystemClock;

import com.aivin.h16_lib.udp.OnReceiveUdpDataCallback;
import com.walkera.wktools.tools.WkByteBitTools;
import com.walkera.wktools.tools.WkLogTool;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

/**
 *  不需要客户端首先发消息的情况。
 *  因为在同一个设备上，回环的，所以服务端可以马上发送信息。
 */
public class UdpClient implements Runnable {
    private static UdpClient server = null;
    private  String ip = "0.0.0.0";
    private  int port = 0;

    /**
     * socket 连接
     */
    private DatagramSocket datagramSocket = null;

    /**
     * 退出标记
     */
    private boolean isExit = false;

    /**
     * 发送方的 ip ,  datagramPacketReceive.getAddress();
     */
    private InetAddress inetAddress =null;
    /**
     * 发送方的 端口 ,datagramPacketReceive.getPort();
     */
    private int clientPort;

    private OnReceiveUdpDataCallback onReceiveUdpDataCallback;

    public synchronized static UdpClient getIntance(){
        if (server == null){
            server = new UdpClient();
        }
        return server;
    }

    public UdpClient setDataListener(OnReceiveUdpDataCallback  callback){
        this.onReceiveUdpDataCallback =callback  ;
        return this;
    }


    public UdpClient initServer(String host , int port ){
        this.ip=host ;
        this.port=port ;
        return this ;
    }

    @Override
    public void run() {
        try {
            datagramSocket = new DatagramSocket(new InetSocketAddress(ip, port)  );
            datagramSocket.setSoTimeout(8000); // 超时
            byte[] msgRcv = new byte[1024];
            DatagramPacket datagramPacketReceive = new DatagramPacket(msgRcv, msgRcv.length);

            while (!isExit) {
                if(datagramSocket==null || datagramSocket.isClosed()){
                    SystemClock.sleep(10);
                    continue;
                }
                // 如receive() 是阻塞接收， 果设置了超时时间，会在时间到了之后报一个错
                datagramSocket.receive(datagramPacketReceive);

                if(inetAddress==null){
                    inetAddress = datagramPacketReceive.getAddress();
                }

                if(clientPort==0 || clientPort==-1){
                    clientPort = datagramPacketReceive.getPort();
                }

                byte[] dataRev= WkByteBitTools.subBytes( datagramPacketReceive.getData(),
                        datagramPacketReceive.getOffset(),datagramPacketReceive.getLength());
                if(onReceiveUdpDataCallback!=null){
                    onReceiveUdpDataCallback.onReceiveUdpData(dataRev);
                }

            } // end while

            closeConnect();// end while

        } catch (Exception e) {
            WkLogTool.showLog("udp Exception---" + e.getMessage());
        }
    }


    /**
     * 退出 udp
     */
    public void exitUdp(){
        isExit = true;
        closeConnect(); // exitUdp
        server =null ;
        WkLogTool.showLog("关闭udp");
    }

    private void closeConnect(){
        if (datagramSocket != null){
            if (!datagramSocket.isClosed()){
                datagramSocket.close();
            }
            datagramSocket.disconnect();
            datagramSocket = null;
        }
    }

    /**
     * 发送
     */
    public void sendData( byte[] datas) {
        if(datas==null){
            return;
        }

        if(datagramSocket==null || datagramSocket.isClosed() /*|| (!datagramSocket.isConnected())*/){
            return;
        }

        if(inetAddress==null){
            return;
        }
        if(clientPort==0 || clientPort==-1){
            return;
        }

        try {
            DatagramPacket datagramPacketSend = new DatagramPacket(datas,datas.length, inetAddress,clientPort);
            datagramSocket.send(datagramPacketSend);
        } catch (IOException e) {
            WkLogTool.showLog("udp发送异常="+ e.getMessage());
            e.printStackTrace();
        }
    }

}
